package org.planaz.campusvoting.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.planaz.campusvoting.common.result.Result;
import org.planaz.campusvoting.common.result.Results;
import org.planaz.campusvoting.common.user.UserContext;
import org.planaz.campusvoting.dto.req.UserQueryReq;
import org.planaz.campusvoting.dto.req.UserRegisterReq;
import org.planaz.campusvoting.exception.ServiceException;
import org.planaz.campusvoting.mapper.UserMapper;
import org.planaz.campusvoting.pojo.User;
import org.planaz.campusvoting.service.UserService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static org.planaz.campusvoting.common.constant.RedisCacheConstant.USER_LOGIN_KEY;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public Result<?> login(String username, String password) {
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, username).eq(User::getPassword, password));
        if(user == null){
            throw new ServiceException("-1","用户名或密码错误");
        }
        HashMap<String,String> map = new HashMap<>();
        map.put("username", username);
        Map<Object, Object> hasLoginMap = stringRedisTemplate.opsForHash().entries(USER_LOGIN_KEY + username);
        if (CollUtil.isNotEmpty(hasLoginMap)) {
            stringRedisTemplate.expire(USER_LOGIN_KEY + username, 30L, TimeUnit.DAYS);
            String token = hasLoginMap.keySet().stream()
                    .findFirst()
                    .map(Object::toString)
                    .orElseThrow(() -> new ServiceException("-1","用户登录错误"));
            map.put("token", token);
            return Results.success(map);
        }
        String token = UUID.randomUUID().toString().replace("-", "");
        stringRedisTemplate.opsForHash().put(USER_LOGIN_KEY + username, token, JSON.toJSONString(user));
        stringRedisTemplate.expire(USER_LOGIN_KEY + username, 30L, TimeUnit.DAYS);
        map.put("token", token);
        return Results.success(map);
    }

    @Override
    public Result<?> register(UserRegisterReq userRegisterReq) {
        if(exists(Wrappers.<User>lambdaQuery().eq(User::getUsername, userRegisterReq.getUsername()))) {
            return Results.failure("-1", "用户名已存在");
        }
        if(exists(Wrappers.<User>lambdaQuery().eq(User::getEmail, userRegisterReq.getEmail()))) {
            return Results.failure("-1", "邮箱已被注册");
        }
        String redisCode = stringRedisTemplate.opsForValue().get(userRegisterReq.getEmail()+":register");
        if(redisCode == null || !redisCode.equals(userRegisterReq.getCode())){
            return Results.failure("-1", "验证码错误");
        }
        stringRedisTemplate.delete(userRegisterReq.getEmail()+":register");
        User user = BeanUtil.copyProperties(userRegisterReq, User.class);
        user.setRole("user");
        save(user);
        return Results.success();
    }

    @Override
    public Result<?> loginByEmail(String email, String code) {
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, email));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        String redisCode = stringRedisTemplate.opsForValue().get(email+":login");
        if(redisCode == null || !redisCode.equals(code)){
            return Results.failure("-1", "验证码错误");
        }
        stringRedisTemplate.delete(email+":login");
        return login(user.getUsername(), user.getPassword());
    }

    @Override
    public Result<?> registerByEmail(String email, String password, String code) {
        if(exists(Wrappers.<User>lambdaQuery().eq(User::getEmail, email))) {
            return Results.failure("-1", "邮箱已被注册");
        }
        String redisCode = stringRedisTemplate.opsForValue().get(email+":register");
        if(redisCode == null || !redisCode.equals(code)){
            return Results.failure("-1", "验证码错误");
        }
        stringRedisTemplate.delete(email+":register");
        User user = new User();
        user.setUsername(email);
        user.setEmail(email);
        user.setPassword(password);
        user.setRole("user");
        save(user);
        return Results.success();
    }

    @Override
    public Result<?> resetPasswordByEmail(String email, String password, String code) {
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, email));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        String redisCode = stringRedisTemplate.opsForValue().get(email+":reset_password");
        if(redisCode == null || !redisCode.equals(code)){
            return Results.failure("-1", "验证码错误");
        }
        stringRedisTemplate.delete(email+":reset_password");
        user.setPassword(password);
        updateById(user);
        return Results.success();
    }

    @Override
    public Result<?> resetPassword(String password) {
        Long userId = UserContext.getUserId();
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, userId));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        user.setPassword(password);
        updateById(user);
        stringRedisTemplate.delete(USER_LOGIN_KEY + user.getUsername());
        return Results.success("密码修改成功，请重新登录");
    }

    @Override
    public Result<?> resetEmail(String email, String code) {
        Long userId = UserContext.getUserId();
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, userId));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        String redisCode = stringRedisTemplate.opsForValue().get(email+":reset_email");
        if(redisCode == null || !redisCode.equals(code)){
            return Results.failure("-1", "验证码错误");
        }
        stringRedisTemplate.delete(email+":reset_email");
        user.setEmail(email);
        updateById(user);
        return Results.success("邮箱修改成功");
    }

    @Override
    public Result<?> getUserInfo() {
        Long userId = UserContext.getUserId();
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, userId));
        if(user != null){
            user.setPassword(null);
            return Results.success(user);
        }
        return null;
    }

    @Override
    public Result<?> changeUserInfo(User userInfo) {
        Long userId = UserContext.getUserId();
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, userId));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        user.setAvatar(userInfo.getAvatar());
        user.setIntroduction(userInfo.getIntroduction());
        user.setSId(userInfo.getSId());
        updateById(user);
        return Results.success("信息修改成功");
    }

    @Override
    public Result<?> query(Page<User> userPage, UserQueryReq userQueryReq) {
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        if(userQueryReq!=null){
            if(userQueryReq.getUsernameLike()!=null){
                wrapper.like("username",userQueryReq.getUsernameLike());
            }
            if(userQueryReq.getEmailLike()!=null){
                wrapper.like("email",userQueryReq.getEmailLike());
            }
            if(userQueryReq.getStatusEq()!=null){
                wrapper.eq("status",userQueryReq.getStatusEq());
            }
            if (userQueryReq.getOrderBy()!=null){
                wrapper.orderBy(true,userQueryReq.getOrderBy().getIsAsc(),userQueryReq.getOrderBy().getColumn());
            }
        }
        wrapper.eq("del_flag",0);
        Page<User> page = page(userPage, wrapper);
        page.getRecords().forEach(i-> i.setPassword(null));
        return Results.success(page);
    }

    @Override
    public Result<?> ban(Long id) {
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, id));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        if (user.getStatus()==1){
            throw new ServiceException("-1","操作失败，用户已经被封禁");
        }
        user.setStatus(1);
        update(user,Wrappers.<User>lambdaQuery().eq(User::getId, id));
        return Results.success("封禁成功");
    }

    @Override
    public Result<?> unBan(Long id) {
        User user = getOne(Wrappers.<User>lambdaQuery().eq(User::getId, id));
        if(user == null){
            throw new ServiceException("-1","用户不存在");
        }
        if (user.getStatus()==0){
            throw new ServiceException("-1","操作失败，用户未被封禁");
        }
        user.setStatus(0);
        update(user,Wrappers.<User>lambdaQuery().eq(User::getId, id));
        return Results.success("解封成功");
    }
}
